// tge.rs
// copyright zipxing@hotmail.com 2022~2023

//! event模块提供了一个方便的全局事件中心和一个全局定时器中心
//! 采用Mutex全局变量实现，Mutex会损失一点性能，但方便使用
//! 还有一个方案是把Event和Timer两个数据结构放在context里，
//! 但这样要求所有的代码都可以访问context，不是很方便使用
//! 另外，还提供了一个转换sdl的输入事件为crossterm输入事件
//! 的函数，方便游戏采用统一接口处理

use crate::GAME_FRAME;
use lazy_static::lazy_static;
use serde::Serialize;
use std::{collections::HashMap, sync::Mutex};

// 使用全局Mutex变量
lazy_static! {
    pub static ref GAME_TIMER: Mutex<Timers> = Mutex::new(Timers::new());
    pub static ref EVENT_CENTER: Mutex<HashMap<String, HashMap<String, bool>>> =
        Mutex::new(HashMap::new());
}

/// 用全局HashMap来存储事件回调状态
pub fn event_register(event: &str, func: &str) {
    let mut ec = EVENT_CENTER.lock().unwrap();
    match ec.get_mut(event) {
        Some(ht) => {
            ht.insert(func.to_string(), false);
        }
        None => {
            let mut h: HashMap<String, bool> = HashMap::new();
            h.insert(func.to_string(), false);
            ec.insert(event.to_string(), h);
        }
    }
}

pub fn event_check(event: &str, func: &str) -> bool {
    let mut ec = EVENT_CENTER.lock().unwrap();
    match ec.get_mut(event) {
        Some(ht) => match ht.get_mut(func) {
            Some(flag) => {
                if *flag {
                    *flag = false;
                    return true;
                }
            }
            None => {}
        },
        None => {}
    }
    false
}

pub fn event_emit(event: &str) {
    match EVENT_CENTER.lock().unwrap().get_mut(event) {
        Some(ht) => {
            for (_key, value) in ht {
                if *value == false {
                    *value = true;
                }
            }
        }
        None => {}
    }
}

pub fn timer_register(name: &str, time: f32, func: &str) {
    GAME_TIMER.lock().unwrap().register(name, time, func);
}

pub fn timer_set_time(name: &str, time: f32) {
    GAME_TIMER.lock().unwrap().set_time(name, time);
}

pub fn timer_stage(name: &str) -> u32 {
    GAME_TIMER.lock().unwrap().stage(name)
}

pub fn timer_rstage(name: &str) -> u32 {
    GAME_TIMER.lock().unwrap().rstage(name)
}

pub fn timer_percent(name: &str) -> f32 {
    GAME_TIMER.lock().unwrap().percent(name)
}

pub fn timer_exdata(name: &str) -> Option<Vec<u8>> {
    GAME_TIMER.lock().unwrap().exdata(name)
}

pub fn timer_fire<T>(name: &str, value: T)
where
    T: Serialize,
{
    GAME_TIMER.lock().unwrap().fire(name, value);
}

pub fn timer_cancel(name: &str, nall: bool) {
    GAME_TIMER.lock().unwrap().cancel(name, nall);
}

pub fn timer_update() {
    GAME_TIMER.lock().unwrap().update()
}

pub struct Timer {
    time: u32,
    count: u32,
    exdata: Vec<u8>,
}

#[derive(Default)]
pub struct Timers {
    pub timers: HashMap<String, Timer>,
}

impl Timers {
    pub fn new() -> Self {
        Self { ..Self::default() }
    }

    pub fn register(&mut self, name: &str, time: f32, callback: &str) {
        match self.timers.get_mut(name) {
            Some(_) => {}
            None => {
                let timer = Timer {
                    time: 0,
                    count: (time * GAME_FRAME as f32) as u32,
                    exdata: vec![],
                };
                self.timers.insert(name.to_string(), timer);
                event_register(name, callback);
            }
        }
    }

    pub fn stage(&mut self, name: &str) -> u32 {
        match self.timers.get_mut(name) {
            Some(timer) => {
                return timer.time;
            }
            None => {
                return 0;
            }
        }
    }

    pub fn rstage(&mut self, name: &str) -> u32 {
        match self.timers.get_mut(name) {
            Some(timer) => {
                return timer.count - timer.time;
            }
            None => {
                return 0;
            }
        }
    }

    pub fn percent(&mut self, name: &str) -> f32 {
        match self.timers.get_mut(name) {
            Some(timer) => {
                return timer.time as f32 / timer.count as f32;
            }
            None => {
                return 0f32;
            }
        }
    }

    pub fn set_time(&mut self, name: &str, time: f32) {
        match self.timers.get_mut(name) {
            Some(timer) => {
                timer.count = (time * GAME_FRAME as f32) as u32;
                //设置的time太小，会导致count为0，无法触发
                //这里保护一下，设置完后count至少为1
                if timer.count == 0 {
                    timer.count += 1;
                }
            }
            None => {}
        }
    }

    pub fn exdata(&mut self, name: &str) -> Option<Vec<u8>> {
        match self.timers.get_mut(name) {
            Some(timer) => {
                return Some(timer.exdata.clone());
            }
            None => {
                return None;
            }
        }
    }

    pub fn fire<T>(&mut self, name: &str, value: T)
    where
        T: Serialize,
    {
        match self.timers.get_mut(name) {
            Some(timer) => {
                timer.time = timer.count;
                timer.exdata = bincode::serialize(&value).unwrap();
            }
            None => {}
        }
    }

    pub fn cancel(&mut self, name: &str, nocall: bool) {
        match self.timers.get_mut(name) {
            Some(timer) => {
                timer.time = 0;
                if !nocall {
                    event_emit(name);
                }
            }
            None => {}
        }
    }

    pub fn update(&mut self) {
        for (name, timer) in &mut self.timers {
            if timer.time > 0 {
                timer.time -= 1;
                if timer.time == 0 {
                    event_emit(name);
                }
            }
        }
    }
}

